package siedler.GUI.gameElements;

import java.awt.Color;
import java.awt.Graphics;
import java.io.Serializable;
import java.util.ArrayList;

import siedler.GUI.interfaces.Klickable;
import siedler.GUI.interfaces.Paintable;
import siedler.GUI.other.Coordinate;
import siedler.gaming.User;
import util.simpleIO.Out;

/**
 * Conntections between Fields (Streets)
 * 
 * @author Krisi
 */
public class Connection implements Paintable, Klickable, Serializable {
	
	//-----------------------------------------------------------------
	// --- Graphic variables ------------------------------------------
	//
	
	//public static SiedlerGamePanel gamePanel;
	//private final static int   x6E  = SiedlerGamePanel.x6E;		// number of edges/connection
	//private final static int   xAdd = SiedlerGamePanel.xAdd;	// value to add before modulo for index <= 0
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private int nullId=0;				// ID used if one of the fields is null. (1...6). 0 equals not set.
	protected Field field1, field2;		// connected Fields
	private ArrayList<Connection> connectedTo = new ArrayList<Connection>(4);
	private Coordinate klickCoord = zeroCoord;
	private Coordinate position   = zeroCoord;
	
	//-----------------------------------------------------------------
	// --- Game specific stuff ------------------------------------
	//
	public User owner = null;
	
	/**
	 * buildStreet
	 * @param owner
	 * @return true on error
	 */
	public boolean buildStreet(User owner){
		
		boolean err = owner==null;
		this.owner = owner;
		return err;
	}
	
	//-----------------------------------------------------------------
	// --- Initialization ---------------------------------------------
	//
	
	/**
	 * Constructor
	 * @param field1
	 * @param field2
	 */
	public Connection(Field field1, Field field2, int nullId){
		this.field1 = field1;
		this.field2 = field2;
		
		if(field1==null || field2==null)
			this.nullId = nullId;
	}
	
	/**
	 * Add connection (min 2, max 4)
	 * @param c
	 * @return false if connection already connected
	 */
	public boolean connectedTo(Connection c){
		
		//Out.pl("Connecting <"+this+"> to <"+c+">");
		if(connectedTo.contains(c)){
			return false;
		}
		connectedTo.add(c);
		return true;
	}
	
	/**
	 * initGraphics
	 * Initialize the coordinates of the connection.
	 *  -> Position
	 *  -> Klick Area
	 */
	protected void initGraphics(){
		
		Field f             = (field1!=null) ? field1 : field2;		// get a field != null
		@SuppressWarnings("static-access")
		int fieldSize       = f.getFieldSize();						// get the field size
		
		int direction = f.getConnectionNumber(this);				// get the "direction" of this connection
		Coordinate corner1 = f.getCornerPosition(direction  );
		Coordinate corner2 = f.getCornerPosition(direction+1);
		
		position = Coordinate.middle(corner1, corner2);			// middle of the (relative) corners + position
		klickCoord = new Coordinate(position.x1, position.y1, fieldSize/6);	// area around position
	}
	
	//-----------------------------------------------------------------
	// --- Object specific methods ------------------------------------
	//
	
	/**
	 * isConnectedTo
	 * Tests if this connection is connected to the connection c.
	 * @param c
	 * @return true if this connection is next to 'c'
	 */
	public boolean isConnectedTo(Connection c){
		return connectedTo.contains(c);
	}
	/**
	 * isConnectedTo
	 * Tests if this connection is connected to the Field f.
	 * @param c
	 * @return true if this connection is next to 'c'
	 */
	public boolean isConnectedTo(Field f){
		return field1==f || field2==f;
	}
	
	/**
	 * 
	 * @param fStart
	 * @return other FIeld from connection
	 */
	public Field getTarget(Field fStart){
		
		if(fStart==field1)
			return field2;
		if(fStart==field2)
			return field1;
		
		throw new RuntimeException("Field 'fStart' was not in this connection.");
	}
	
	//-----------------------------------------------------------------
	// --- Painting ---------------------------------------------------
	//
	
	@Override
	public void paint(Graphics g) {
		
		//Out.pl("drawing... " + position);
		g.setColor(Color.BLUE);
//		g.drawOval(klickCoord.x1, klickCoord.y1, klickCoord.getWidth(1), klickCoord.getHeight(1));
		//g.drawRect(klickCoord.x1, klickCoord.y1, klickCoord.getWidth(1), klickCoord.getHeight(1));
		//Field.drawX(g, position, 5);
		
		if(this.owner != null)
			drawStreet(g);
	}
	
	public void drawStreet(Graphics g) {

		Coordinate p1 = field1.getFirstCorner(this).getPosition();
		Coordinate p2 = field1.getSecondCorner(this).getPosition();
		
		g.drawLine(p1.x1, p1.y1, p2.x1, p2.y1);
	}
	
	
	//-----------------------------------------------------------------
	// --- Klickable methods ------------------------------------------
	//
	
	@Override
	public Coordinate getPosition() {
		return klickCoord;
	}
	@Override
	public Coordinate getKlickArea(){
		return klickCoord;
	}
	@Override
	public boolean isKlickedBy(int x, int y) {
		return klickCoord.contains(x,y);
	}
	@Override
	public boolean klickIt() {
		Out.pl("Klicked: " + this + " ("+this.position+")");
		if(owner==null){
			buildStreet( new User() );
			System.out.println("IFFFFFF Owner == null");
			return true;
		}
		return true;
	}
	
	//-----------------------------------------------------------------
	// --- Testing methods --------------------------------------------
	//
	
	/**
	 * Final test for correctness.
	 */
	public void finalTest(){
		
		if(field1==null && field2==null)
			throw new RuntimeException("Fields were null");
		
		if(field1==null || field2==null)
			if(nullId==0)
				throw new RuntimeException("Null-ID not set in null-connection!");
		
		if(connectedTo.size()<2 && connectedTo.size()>4)
			throw new RuntimeException("Wrong number of connections! ("+connectedTo.size()+")");
	}
	
	//-----------------------------------------------------------------
	// --- Other methods ----------------------------------------------
	//
	
	/**
	 * Overwritten equals method from object.
	 * 
	 */
	public boolean equals(Object o){
		
		if(o instanceof Connection){			// test if it is an Connection
			Connection c = (Connection) o;		// cast to connection
			
			if(	c.field1==field1 && c.field2 == field2 ||		// test equality
				c.field1==field2 && c.field2 == field1    ) {	// -
				
				if(c.field1==null || c.field2==null)			// Connection to null:
					return c.nullId==0 || nullId==0 || 			//  -> Test IDs (more than 1 null-connection allowed)
							c.nullId==nullId;					//  -> zero nullId is "joker"
				else											// Normal connection:
					return true;								//  -> true
			}
		}
		return false;
	}

	@Override
	public String toString(){
		String id="";
		if(field1==null || field2==null)
			id = "#"+nullId+"";
			
		return "Connection: "+field1+"->"+field2+""+id;
	}
	public String toString(Field f){
		return "Connection: '"+f.getConnectionNumber(this)+"'";
	}

}
